﻿// Shader-Based-Image-Processing (SBIP)
// http://code.google.com/p/sbip/
//
// Copyright © Frank Nagl, 2009-2010
// admin@franknagl.de
//
namespace SBIP.Filter
{
    /// <summary>
    /// Sobel edge detector.
    /// </summary>
    /// <remarks><para>The filter searches for objects' edges by applying Sobel operator.</para>
    /// 
    /// <para>Each pixel of the result image is calculated as approximated absolute gradient
    /// magnitude for corresponding pixel of the source image:
    /// <code lang="none">
    /// |G| = |Gx| + |Gy] ,
    /// </code>
    /// where Gx and Gy are calculate utilizing Sobel convolution kernels:
    /// <code lang="none">
    ///    Gx         Gy
    /// -1 0 +1    +1 +2 +1
    /// -2 0 +2     0  0  0
    /// -1 0 +1    -1 -2 -1
    /// </code>
    /// Using the above kernel the approximated magnitude for pixel <b>x</b> is calculate using
    /// the next equation:
    /// <code lang="none">
    /// P1 P2 P3
    /// P8  x P4
    /// P7 P6 P5
    /// 
    /// |G| = |P1 + 2P2 + P3 - P7 - 2P6 - P5| +
    ///       |P3 + 2P4 + P5 - P1 - 2P8 - P7|
    /// </code>
    /// </para>
    ///	
    /// <para>Sample usage:</para>
    /// <code>
    /// Bitmap image = new Bitmap( "cathedral.jpg" );
    ///
    /// // 1. Offline rendering of images
    /// // create Processor, used as rendering framework
    /// Processor processor = new Processor( );
    /// // starts Processor
    /// processor.Begin( image );
    /// // create SobelEdgeDetector filter
    /// SobelEdgeDetector filter = new SobelEdgeDetector( );
    /// processor.Filter = filter;
    /// // optional: configure filter
    /// filter.IsColored = true;
    /// filter.Threshold = 150;
    /// // apply the filter, render to bitmap  
    /// Bitmap resultImage = processor.RenderToBitmap( );
    /// resultImage.Save( "SobelEdgeDetector.jpg", ImageFormat.Jpeg );
    /// // apply the filter, render to texture
    /// // Texture2D resultTexture = processor.RenderToTexture( );
    /// processor.End( );
    ///  
    /// // 2. Online rendering of videos or images
    /// // create any windows control for rendering in
    /// Form myForm = new Form
    /// {
    ///     Width = 1280,
    ///     Height = 720
    /// };
    /// // starts Processor
    /// processor.Begin( "Video.avi", myForm );
    /// // create SobelEdgeDetector filter
    /// filter = new SobelEdgeDetector( );
    /// processor.Filter = filter;
    /// // optional: configure filter
    /// filter.IsBlackWhite = true;
    /// filter.Threshold = 180;
    /// // apply the filter
    /// myForm.Show( );
    /// while ( myForm.Created )
    /// {
    ///     processor.Render( );
    ///     Application.DoEvents( );
    /// }
    /// processor.End( );
    /// </code>
    /// 
    /// <para><b>Initial image:</b></para>
    /// <img src="../../Cathedral.jpg" width="500" height="338" />
    /// <para><b>Result image:</b></para>
    /// <img src="../../SobelEdgeDetector.jpg" width="500" height="338" />
    /// </remarks>
    public sealed class SobelEdgeDetector : BaseFilter
    {
        private bool isColored;
        private bool isBlackWhite;
        private byte threshold;
        /// <summary>
        /// Indicating whether edge image is colored of grayscaled. 
        /// Default: false.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if edge image will be colored, 
        /// 	otherwise edge image is grayscaled.
        /// </value>
        public bool IsColored
        {
            get { return isColored; }
            set
            {
                if (Effect == null)
                    throw new System.ArgumentException("IsColored" + InitMsg);

                isColored = value;
                Effect.Parameters["IsColored"].SetValue(value);

            }
        }

        /// <summary>
        /// Indicating whether edge image is drawn as black-white image. 
        /// Default: false.
        /// Note: If true, a correct <see cref="Threshold"/> value is needed.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if edge image will be  drawn as black-white image.
        /// </value>
        public bool IsBlackWhite
        {
            get { return isBlackWhite; }
            set
            {
                if (Effect == null)
                    throw new System.ArgumentException("IsBlackWhite" + InitMsg);

                isBlackWhite = value;
                Effect.Parameters["IsBlackWhite"].SetValue(value);

            }
        }

        /// <summary>
        /// The threshold value. Default: 0 (no threshold).
        /// </summary>
        public byte Threshold
        {
            get { return threshold; }
            set
            {
                if (Effect == null)
                    throw new System.ArgumentException("Threshold" + InitMsg);

                threshold = value;
                Effect.Parameters["Threshold"].SetValue(value / 255.0f);

            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SobelEdgeDetector"/> 
        /// class.
        /// </summary>        
        public SobelEdgeDetector() : base("SobelEdgeDetector") { }

        /// <summary>
        /// Defines, that Sobel edge detector is not colored.
        /// </summary>
        protected override void PostInit()
        {
            IsColored = false;
            Threshold = 0;
        }
    }
}
